package com.wbf.demo.service;

import com.wbf.demo.domain.Menu;
import com.wbf.demo.domain.Role;
import com.wbf.demo.domain.Subject;
import com.wbf.demo.mapper.MenuMapper;
import com.wbf.demo.mapper.RoleMapper;
import com.wbf.demo.mapper.UserMapper;
import com.wbf.demo.mobile.User;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @program: security_demo
 * @description: 登陆业务处理
 * @author: guangdao
 * @create: 2022-04-14 18:46
 **/
@Service
public class LoginService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private MenuMapper menuMapper;
    /**
     * 用户名密码登录
     * @param username
     * @param password
     * @return
     * @throws UsernameNotFoundException
     */
    public UserDetails loadUserByUsername(String username, String password) throws UsernameNotFoundException {
        User user = userMapper.getUserByUsernamePassword(username,password);
        if(user == null){
            throw new BadCredentialsException("用户名或密码错误");
        }
        Subject subject = new Subject();
        BeanUtils.copyProperties(user,subject);
        List<Role> roleList = roleMapper.getUserRoleList(user.getId());
        List<Menu> menuList = new ArrayList<>();
        for(Role role :roleList){
            role.setMenuList(menuMapper.getMenuListByRoleId(role.getId()));
            menuList.addAll(role.getMenuList());
        }
        subject.setRoleList(roleList);
        menuList = menuList.stream().filter(distinctByKey(menu->menu.getId())).collect(Collectors.toList());
        subject.setMenuList(menuList);
        return subject;
    }

    static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Map<Object,Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
}
